----一些公共方法
----#include "..\..\language\LangCode.txt" once
--#include "data\envir\FuBen.txt" once
--#include "data\functions\Common\CommonFunc.lua" once				--一些通用方法
--#include "data\config\common\CommonSceneConfig.lua" once			--一些通用配置
--#include "data\functions\Guild\GuildContendWar.lua" once          --行会争夺    

----------------场景相关方法的回调处理---------begin---------------------------
SceneEnterDispatcher 		= {}					--进入场景、副本的回调
SceneExitDispatcher 		= {}					--离开场景的回调(回调方法中决不能再有离开、进入场景副本的方法，否则会导致无限循环)
FubenExitDispatcher 		= {}					--离开副本的回调(回调方法中决不能再有离开、进入场景副本的方法，否则会导致无限循环)
SceneLogoutDispatcher 		= {}					--场景、副本中下线的回调
FubenTimeoutDispatcher 		= {}					--副本时间到的回调
SceneDieDispatcher 			= {}					--场景、副本中被击杀的回调（与SceneDeathDispatcher的区别是有killer）
SceneDeathDispatcher 		= {}					--场景、副本中被死亡的回调（与SceneDieDispatcher的区别是没有killer）
SceneReliveDispatcher 		= {}					--场景、副本中复活的回调
SceneAwardDispatcher 		= {}					--场景、副本中领奖的回调
SceneHandExitDispatcher		= {}					--手工离开场景、副本的回调
----------------场景相关方法的回调处理---------end---------------------------

--从Fuben.txt中注册离开副本的方法
function RegisterFubenProc()
	for i, fubenCfg in ipairs( FuBen ) do
		if fubenCfg.teleport then			--这个副本有传送点，角色可能通过传送点离开
			--print("*****>> RegisterFubenProc, fubenId="..fubenCfg.fbid)
			FubenExitDispatcher.register( fubenCfg.fbid,  OnCommonFubenExit )				--注册离开场景、副本后触发的事件
		end
	end
end

--[[
此方法用于角色从场景、副本外通过合法途径进入场景、副本
掉线重登陆场景、副本不要使用此方法
beforeRealConsumeFunc: 在执行扣除进入场景费用之前一步执行的方法，注意，如果要扣除消耗，则所消耗的物品不要与进入场景的费用重复
beforEnterFunc：       在正式进入场景、副本之前一步执行的方法
]]
function CommonEnterScence( sysarg, sceneCfg, enterLogId, enterLogDesc, beforeRealConsumeFunc, beforEnterFunc )
	if not Actor.canTelport(sysarg, sceneCfg.sceneId) then               --是否允许场景传送
		--Actor.sendTipmsg(sysarg, Lang.ScriptTips.COM0020,ttFlyTip)
		return false
	end

	return DoCommonEnterScence( sysarg, sceneCfg, enterLogId, enterLogDesc, beforeRealConsumeFunc, beforEnterFunc )
end

function DoCommonEnterScence( sysarg, sceneCfg, enterLogId, enterLogDesc, beforeRealConsumeFunc, beforEnterFunc )
	--print("DoCommonEnterScence, sceneId="..sceneCfg.sceneId)
	if Actor.getSceneId( sysarg ) == sceneCfg.sceneId then				--已经在场景中
		Actor.sendTipmsg(sysarg, Lang.ScriptTips.COM0032,ttFlyTip)
		return false
	end

	if sceneCfg.enterLevelLimit then			            --判断进入等级要求
		if not Actor.checkActorLevel( sysarg, sceneCfg.enterLevelLimit[2], sceneCfg.enterLevelLimit[1] ) then
    		Actor.sendTipmsg(sysarg, Lang.ScriptTips.COM0016,ttFlyTip)
    		return false
    	end
	end

	--注意：openServerDay不再使用，仅供兼容以前的代码
	local openDays = System.getDaysSinceOpenServer()
	if sceneCfg.openServerDay and sceneCfg.openServerDay > 0 and openDays < sceneCfg.openServerDay then 			--单开服天数判断
		Actor.sendTipmsg(sysarg, string.format(Lang.ScriptTips.COM0071, sceneCfg.openServerDay-openDays),ttFlyTip)
		return false
	end

	--开服前N1天或者合服前N2天的判断
	local combDays = System.getDaysSinceCombineServer()
	if sceneCfg.openOrCombServerDay and not CheckOpenOrCombServerDayBegore( sceneCfg.openOrCombServerDay ) then
		Actor.sendTipmsg( sysarg, Lang.ScriptTips.COM0098, ttFlyTip )
		return false
	end

	if sceneCfg.enterDayLimit then  --注意：这里开服、合服天数是或的关系
		if not CheckSceneEnterDayLimit( sceneCfg ) then
			Actor.sendTipmsg(sysarg, Lang.ScriptTips.COM0072, ttFlyTip)
			return false
		end
	end

	if sceneCfg.enterLevelMin and sceneCfg.enterLevelMax then		--判断进入等级区间要求
		local circle = Actor.getIntProperty(sysarg, PROP_ACTOR_CIRCLE)
		local level  = Actor.getIntProperty(sysarg, PROP_CREATURE_LEVEL)
		if sceneCfg.enterLevelMin[1] <= circle and circle <= sceneCfg.enterLevelMax[1] and
		   sceneCfg.enterLevelMin[2] <= level  and level  <= sceneCfg.enterLevelMax[2] then
		else
			Actor.sendTipmsg(sysarg, Lang.ScriptTips.COM0045,ttFlyTip)
    		return false
		end
	end

	if sceneCfg.enterVipLimit then
		local needVip = 0
		if openDays <= sceneCfg.enterVipLimit[1] then
			needVip = sceneCfg.enterVipLimit[2] 		--开服N天内需要VIP等级
		else
			needVip = sceneCfg.enterVipLimit[3] 		--开服N天后需要VIP等级
		end

		if needVip > 0 and Actor.getVipGrade( sysarg ) < needVip then
			Actor.sendTipmsg(sysarg, string.format( Lang.ScriptTips.COM0050, needVip ), ttFlyTip)
			return false
		end
	end
	if sceneCfg.vipType then
		if not Actor.isConcurrentVip(sysarg, sceneCfg.vipType) then
			Actor.sendTipmsg(sysarg, Lang.ScriptTips.COM0107, ttFlyTip)
			return
		end
	end

	--每日充值金额要求（元宝）
	if sceneCfg.enterDailyRechargeLimit and sceneCfg.enterDailyRechargeLimit > 0 then
		local todayRechargeNum = Actor.getDailyChargeYuanBao( sysarg )
		if todayRechargeNum < sceneCfg.enterDailyRechargeLimit then
			Actor.sendTipmsg(sysarg, Lang.ScriptTips.COM0099, ttFlyTip)
			return false
		end
	end

	--local nowSceneId = Actor.getSceneId( sysarg )
	--print("DoCommonEnterScence, nowSceneId="..nowSceneId)
	if not sceneCfg.noCheckFromScene and IsSceneCannotToFuben( sysarg ) then	--需要判断进入场景并且不能从当前场景进入
		Actor.sendTipmsg(sysarg, Lang.ScriptTips.COM0094,ttFlyTip)
		return false
	end

	--判断进入场景的费用是否足够
	if sceneCfg.enterConsume and not CheckConsumeCond( sysarg, sceneCfg.enterConsume, 1, sceneCfg.sendTipmsg ) then
		return false
	end

	--此判断，必须在马上要执行真正扣费时才能进行；此判断通过，就真正执行扣除进入场景的费用
	if beforeRealConsumeFunc and not beforeRealConsumeFunc( sysarg, sceneCfg ) then
		return false
	end

	local fubenHandle = 0
	if sceneCfg.fubenId and sceneCfg.fubenId > 0 then			--进入副本
		local nowFubenId = Actor.getFubenId( sysarg )
		--print("CommonEnterScence, nowFubenId="..nowFubenId)
		if nowFubenId == 0 then									--在副本外
			fubenHandle = Fuben.createFuBen( sceneCfg.fubenId )
			if fubenHandle > 0 and sceneCfg.reloginType == 2 then 		    --多人行会副本需要掉线恢复
				local guildId = Actor.getGuildId(sysarg)
				Fuben.setGuildId( fubenHandle, guildId) 		--多人行会副本需要设置掉线保护，设置guildId，以便重登陆时校验，不让外人进入
			end
		elseif nowFubenId == sceneCfg.fubenId then 	            --已经在该副本中
			fubenHandle = Actor.getFubenHandle( sysarg )
		else 													--在别的副本中，要先退出
			Actor.sendTipmsg(sysarg, Lang.ScriptTips.COM0040,ttFlyTip)
			return false
		end
		
		--print("CommonEnterScence, fubenHandle="..fubenHandle)
		if not fubenHandle then
			return false
		end
	end

	local enterPos = nil
	if sceneCfg.enterPos then
		enterPos = sceneCfg.enterPos
	elseif sceneCfg.enterPosRand then
		local idx, randPos = GetItemIdxRandNoWeight( sceneCfg.enterPosRand )
		enterPos = randPos
	end

	if not enterPos then
		return false
	end

	--扣除进入场景的费用
	if sceneCfg.enterConsume and  not DoConsumeCond( sysarg, sceneCfg.enterConsume, 1, enterLogId or 0, enterLogDesc or "", sceneCfg.sendTipmsg) then
		return false
	end

	--此方法，需要在真正进入场景之前执行，执行过后，进立即进入场景
	if beforEnterFunc and not beforEnterFunc( sysarg, sceneCfg ) then
		return false
	end

	if fubenHandle <= 0 then		--进入场景
		local result = Actor.enterScene(sysarg, sceneCfg.sceneId, enterPos[1], enterPos[2])
		if result then
			if sceneCfg.autoFreshMonster and sceneCfg.monsters then		--进场景自动刷怪
				FreshCommonMonsters( sceneCfg.monsters, 0, true )
			end
		end
		return result
	else 							--进入副本
		local result = Actor.enterFuBen(sysarg, fubenHandle, sceneCfg.sceneId, enterPos[1], enterPos[2])
		if result then
			local fubenPtr = Actor.getFubenPrt( sysarg )
			if fubenPtr then
				if sceneCfg.autoFreshMonster and sceneCfg.monsters then			--进副本自动刷怪
					FreshCommonMonsters( sceneCfg.monsters, fubenHandle, true )
				end

				if sceneCfg.reloginType == 1 then 		--个人副本需要掉线恢复
					local actorId = Actor.getActorId( sysarg )
					Fuben.setOwnerId( fubenPtr, actorId ) 			--单人副本需要设置掉线保护，设置ownerId()，以便重登陆时校验
				end
			end
		end
		return result
	end
end

--[[
检查场景的开放天数要求
]]
function CheckSceneEnterDayLimit( sceneCfg )
	local openDays = System.getDaysSinceOpenServer()
	local combDays = System.getDaysSinceCombineServer()
	
	local openDayLimit = true
	if sceneCfg.enterDayLimit.openDay and openDays < sceneCfg.enterDayLimit.openDay then 	--有开服天数要求
		openDayLimit = false
	end

	local combDayLimit = true
	if sceneCfg.enterDayLimit.combDay and combDays < sceneCfg.enterDayLimit.combDay then 	--有合服天数要求
		combDayLimit = false
	end

	--开服天数不满足要求，并且合服天数也不满足要求
	if not openDayLimit and not combDayLimit then
		return false
	end
	return true
end

--[[
从这些场景中不能进入另一个场景或副本
]]
function IsSceneCannotToFuben( sysarg )
	return IsElemInList( GlobalConfig.scenesNotEnter, Actor.getSceneId( sysarg ) )
end

--注册进入场景后调用的方法
SceneEnterDispatcher.register = function( sceneId, proc )
	--print("----->SceneEnterDispatcher.register, sceneId="..sceneId)
	if not proc then
		print("SceneEnterDispatcher Register, sceneId["..sceneId.."]，proc is nil")
	end

	local callTable = SceneEnterDispatcher[sceneId]
	if not callTable or type(callTable) ~= "table" then
    	SceneEnterDispatcher[sceneId] = {}
    else
    	for i,v in ipairs( callTable ) do
    		if callTable[i] == proc then
        		return
      		end
    	end
    end
    table.insert( SceneEnterDispatcher[sceneId], proc )
	--SceneEnterDispatcher[sceneId] = proc
end

--触发进入场景后调用的方法
SceneEnterDispatcher.dispatch = function( sysarg, sceneId, lastSceneId ) 
	--print("----->SceneEnterDispatcher.dispatch, sceneId="..sceneId)
	local callTable = SceneEnterDispatcher[sceneId]
	if callTable then
		for i, sceneEnterCallProc in ipairs( callTable ) do
			sceneEnterCallProc( sysarg, sceneId, lastSceneId )
		end
		return true
	end
	return false
end

--[[注册离开场景后调用的方法
注意：所注册的方法中不要执行enter场景的操作，以免造成无限循环
]]
SceneExitDispatcher.register = function( sceneId, proc )
	--print("----->SceneExitDispatcher.register, sceneId="..sceneId)
	if not proc then
		print("SceneExitDispatcher Register, sceneId["..sceneId.."]，proc is nil")
	end

	local callTable = SceneExitDispatcher[sceneId]
	if not callTable or type(callTable) ~= "table" then
    	SceneExitDispatcher[sceneId] = {}
    else
    	for i,v in ipairs( callTable ) do
    		if callTable[i] == proc then
        		return
      		end
    	end
    end
    table.insert( SceneExitDispatcher[sceneId], proc )

	--SceneExitDispatcher[sceneId] = proc
end

--[[触发离开场景后调用的方法
包括：主动离开、被T出、下线
注意：离开场景，但仍旧可能在副本中
]]
SceneExitDispatcher.dispatch = function( sysarg, sceneId, fubenId ) 
	--print("----->SceneExitDispatcher.dispatch, sceneId="..sceneId..", fubenId="..fubenId)
	local callTable = SceneExitDispatcher[sceneId]
	if callTable then
		for i, sceneExitCallProc in ipairs( callTable ) do
			sceneExitCallProc( sysarg, sceneId, fubenId )
		end
		return true
	end
	return false
end


--[[注册离开副本后调用的方法
注意：所注册的方法中不要执行enter场景的操作，以免造成无限循环
]]
FubenExitDispatcher.register = function( fubenId, proc )
	--print("----->FubenExitDispatcher.register, fubenId="..fubenId)
	if not proc then
		print("FubenExitDispatcher Register, fubenId["..fubenId.."]，proc is nil")
	end

	local callTable = FubenExitDispatcher[fubenId]
	if not callTable or type(callTable) ~= "table" then
    	FubenExitDispatcher[fubenId] = {}
    else
    	for i,v in ipairs( callTable ) do
    		if callTable[i] == proc then
        		return
      		end
    	end
    end
    table.insert( FubenExitDispatcher[fubenId], proc )
end

--[[触发离开副本后调用的方法
包括：主动离开、被T出、下线
]]
FubenExitDispatcher.dispatch = function( sysarg, fubenId, sceneId ) 
	--print("----->FubenExitDispatcher.dispatch, fubenId="..fubenId..", sceneId="..sceneId)
	local callTable = FubenExitDispatcher[fubenId]
	if callTable then
		for i, fubenExitCallProc in ipairs( callTable ) do
			fubenExitCallProc( sysarg, fubenId, sceneId )
		end
		return true
	end
	return false
end


--[[注册离开场景后调用的方法
注意：所注册的方法中不要执行enter场景的操作，以免造成无限循环
]]
SceneHandExitDispatcher.register = function( sceneId, proc )
	--print("----->SceneHandExitDispatcher.register, sceneId="..sceneId)
	if not proc then
		print("SceneHandExitDispatcher Register, sceneId["..sceneId.."]，proc is nil")
	end

	local callTable = SceneHandExitDispatcher[sceneId]
	if not callTable or type(callTable) ~= "table" then
    	SceneHandExitDispatcher[sceneId] = {}
    else
    	for i,v in ipairs( callTable ) do
    		if callTable[i] == proc then
        		return
      		end
    	end
    end
    table.insert( SceneHandExitDispatcher[sceneId], proc )

	--SceneExitDispatcher[sceneId] = proc
end

--[[
发手工离开场景、副本后调用的方法
注意：此时玩家还在场景、副本中
]]
SceneHandExitDispatcher.dispatch = function( sysarg ) 
	--print("----->SceneHandExitDispatcher.dispatch...")
	local sceneId = Actor.getSceneId( sysarg )
	local callTable = SceneHandExitDispatcher[sceneId]
	if callTable then
		for i, sceneHandExitCallProc in ipairs( callTable ) do
			sceneHandExitCallProc( sysarg )
		end
		return true
	end
	return false
end




--注册场景、副本中下线的调用的方法
SceneLogoutDispatcher.register = function( sceneId, proc )
	--print("----->SceneLogoutDispatcher.register, sceneId="..sceneId)
	if not proc then
		print("SceneLogoutDispatcher Register, sceneId["..sceneId.."]，proc is nil")
	end

	local callTable = SceneLogoutDispatcher[sceneId]
	if not callTable or type(callTable) ~= "table" then
    	SceneLogoutDispatcher[sceneId] = {}
    else
    	for i,v in ipairs( callTable ) do
    		if callTable[i] == proc then
        		return
      		end
    	end
    end
    table.insert( SceneLogoutDispatcher[sceneId], proc )

	--SceneLogoutDispatcher[sceneId] = proc
end

--[[触发场景、副本中下线调用的方法
function OnPlayerLogout(sysarg) 中调用
先于FubenTimeoutDispatcher.dispatch()触发
]]
SceneLogoutDispatcher.dispatch = function( sysarg ) 
	local sceneId = Actor.getSceneId( sysarg )
	--print("----->SceneLogoutDispatcher.dispatch, sceneId="..sceneId)
	local callTable = SceneLogoutDispatcher[sceneId]
	if callTable then
		for i, sceneLogoutCallProc in ipairs( callTable ) do
			sceneLogoutCallProc( sysarg )
		end
		return true
	end
	return false
end


--注册副本时间到的调用的方法
FubenTimeoutDispatcher.register = function( fubenId, proc )
	--print("----->FubenTimeoutDispatcher.register, fubenId="..fubenId)
	if not proc then
		print("FubenTimeoutDispatcher Register, fubenId["..fubenId.."]，proc is nil")
	end

	local callTable = FubenTimeoutDispatcher[fubenId]
	if not callTable or type(callTable) ~= "table" then
    	FubenTimeoutDispatcher[fubenId] = {}
    else
    	for i,v in ipairs( callTable ) do
    		if callTable[i] == proc then
        		return
      		end
    	end
    end
    table.insert( FubenTimeoutDispatcher[fubenId], proc )

	--FubenTimeoutDispatcher[fubenId] = proc
end

--触发副本时间到的调用的方法
FubenTimeoutDispatcher.dispatch = function( fubenId, fubenPtr )
	--print("----->FubenTimeoutDispatcher.dispatch, fubenId="..fubenId)
	local callTable = FubenTimeoutDispatcher[fubenId]
	if callTable then
		for i, fubenTimeoutCallProc in ipairs( callTable ) do
			fubenTimeoutCallProc( fubenPtr )
		end
		return true
	end
	return false
end


--注册场景、副本中被击杀的调用的方法
SceneDieDispatcher.register = function( sceneId, proc )
	--print("----->SceneDieDispatcher.register, sceneId="..sceneId)
	if not proc then
		print("SceneDieDispatcher Register, sceneId["..sceneId.."]，proc is nil")
	end

	local callTable = SceneDieDispatcher[sceneId]
	if not callTable or type(callTable) ~= "table" then
    	SceneDieDispatcher[sceneId] = {}
    else
    	for i,v in ipairs( callTable ) do
    		if callTable[i] == proc then
        		return
      		end
    	end
    end
    table.insert( SceneDieDispatcher[sceneId], proc )

	--SceneDieDispatcher[sceneId] = proc
end

--[[触发场景、副本中被击杀调用的方法
]]
SceneDieDispatcher.dispatch = function( sysarg, killerPtr )
	local sceneId = Actor.getSceneId( sysarg )
	--print("----->SceneDieDispatcher.dispatch, sceneId="..sceneId)
	local callTable = SceneDieDispatcher[sceneId]
	if callTable then
		for i, sceneDieCallProc in ipairs( callTable ) do
			sceneDieCallProc( sysarg, killerPtr )
		end
		return true
	end
	return false
end



--注册场景、副本中死亡的调用的方法
SceneDeathDispatcher.register = function( sceneId, proc )
	--print("----->SceneDeathDispatcher.register, sceneId="..sceneId)
	if not proc then
		print("SceneDeathDispatcher Register, sceneId["..sceneId.."]，proc is nil")
	end

	local callTable = SceneDeathDispatcher[sceneId]
	if not callTable or type(callTable) ~= "table" then
    	SceneDeathDispatcher[sceneId] = {}
    else
    	for i,v in ipairs( callTable ) do
    		if callTable[i] == proc then
        		return
      		end
    	end
    end
    table.insert( SceneDeathDispatcher[sceneId], proc )

	--SceneDieDispatcher[sceneId] = proc
end

--[[触发场景、副本中死亡调用的方法
]]
SceneDeathDispatcher.dispatch = function( sysarg )
	local sceneId = Actor.getSceneId( sysarg )
	--print("----->SceneDeathDispatcher.dispatch, sceneId="..sceneId)
	local callTable = SceneDeathDispatcher[sceneId]
	if callTable then
		for i, sceneDeathCallProc in ipairs( callTable ) do
			sceneDeathCallProc( sysarg )
		end
		return true
	end
	return false
end



--[[注册场景、副本中复活的调用的方法
注意：所注册的回调方法中需要自己处理回血、回蓝、复活位置等相关逻辑
]]
SceneReliveDispatcher.register = function( sceneId, proc )
	--print("----->SceneReliveDispatcher.register, sceneId="..sceneId)
	if not proc then
		print("SceneReliveDispatcher Register, sceneId["..sceneId.."]，proc is nil")
	end

	local callTable = SceneReliveDispatcher[sceneId]
	if not callTable or type(callTable) ~= "table" then
    	SceneReliveDispatcher[sceneId] = {}
    else
    	for i,v in ipairs( callTable ) do
    		if callTable[i] == proc then
        		return
      		end
    	end
    end
    table.insert( SceneReliveDispatcher[sceneId], proc )

	--SceneReliveDispatcher[sceneId] = proc
end

--[[触发场景、副本中复活的调用的方法
]]
SceneReliveDispatcher.dispatch = function( sysarg, reliveType ) 
	local sceneId = Actor.getSceneId( sysarg )
	--print("----->SceneReliveDispatcher.dispatch, sceneId="..sceneId)
	local callTable = SceneReliveDispatcher[sceneId]
	if callTable then
		for i, sceneReliveCallProc in ipairs( callTable ) do
			sceneReliveCallProc( sysarg, reliveType )
		end
		return true
	end
	return false
end


--[[注册场景、副本中复活的调用的方法
注意：所注册的回调方法中需要自己处理回血、回蓝、复活位置等相关逻辑
]]
SceneAwardDispatcher.register = function( sceneId, proc )
	--print("----->SceneAwardDispatcher.register, sceneId="..sceneId)
	if not proc then
		print("SceneAwardDispatcher Register, sceneId["..sceneId.."]，proc is nil")
	end

	local callTable = SceneAwardDispatcher[sceneId]
	if not callTable or type(callTable) ~= "table" then
    	SceneAwardDispatcher[sceneId] = {}
    else
    	for i,v in ipairs( callTable ) do
    		if callTable[i] == proc then
        		return
      		end
    	end
    end
    table.insert( SceneAwardDispatcher[sceneId], proc )

	--SceneAwardDispatcher[sceneId] = proc
end

--[[触发场景、副本中领奖的回调方法
]]
SceneAwardDispatcher.dispatch = function( sysarg, awardRate ) 
	local sceneId = Actor.getSceneId( sysarg )
	--print("----->SceneReliveDispatcher.dispatch, sceneId="..sceneId)
	local callTable = SceneAwardDispatcher[sceneId]
	if callTable then
		for i, sceneAwardCallProc in ipairs( callTable ) do
			sceneAwardCallProc( sysarg, awardRate )
		end
		return true
	end
	return false
end


--[[
--统一的退出场景回调(saveDb之后调用)
注意：副本与场景是不同的，一个副本可能包括多个场景
退出场景，可能还是在副本中，只是切换场景；SceneHandExitDispatcher
退出副本，一定是退出场景
这个是实体已经退出场景的回调(修改这个请通知)
Actor.exitFuben(sysarg)	会将此方法触发
副本时间到被踢出副本，也会触发此方法
即便通过外挂离开场景，也会触发此方法，对于安全性要求较高的逻辑，可以使用
  sceneId:所离开的场景ID
  fubenId:所离开的副本ID
]]
function OnExitSceneScript(sysarg, sceneId, fubenId)
	--print("OnExitSceneScript, sceneId="..sceneId)
	OnSbkActorExitScene(sysarg, sceneId)
	OnActorExitCommonScene( sysarg, sceneId )
	SceneExitDispatcher.dispatch( sysarg, sceneId, fubenId )

	if fubenId > 0 then
		FubenExitDispatcher.dispatch( sysarg, fubenId, sceneId )
	end
end

--[[进入场景回调
	这个是实体已经进入新场景（sceneId）的回调
	即便通过外挂进入场景，也会触发此方法，对于安全性要求较高的逻辑，可以使用
	sceneId:所进入的的场景ID
	lastSceneId:上一个场景ID，0-没有上一个场景（即玩家登陆游戏）
]]
function OnEnterSceneScript(sysarg, sceneId, lastSceneId)
	--print("OnEnterSceneScript, sceneId="..sceneId..", lastSceneId="..lastSceneId)
    onSbkEnterScene(sysarg, sceneId, lastSceneId)
    onContendEnterScene(sysarg, sceneId, lastSceneId)
    onDreamLandBossEnterScene(sysarg, sceneId, lastSceneId)

    OnActorEnterCommonScene( sysarg, sceneId )

	if SceneEnterDispatcher.dispatch( sysarg, sceneId, lastSceneId  ) then			--执行了注册事件，就直接返回
		return
	end

	OnBossHomeChange( sysarg, sceneId, lastSceneId )
	TwelvePalacesOnChange( sysarg, sceneId, lastSceneId )
	
	if Actor.hasState(sysarg,esStateAnswer) then
		TerminatePersonAnswer( sysarg )						--切换场景，终止答题
	end
end

--[[
(离开场景)回到主城的某个范围中的一个点
离开副本不要使用此方法
]]
function BackToMainCity( sysarg )
	local sceneId = 4
	local range   = {60, 49, 68, 61}		--{左下角x,左下角y, 右上角x,右上角y}
	SendToSceneInRange(sysarg, sceneId, range)
end

--随机传送到某个场景的某个区域，避免人数集中在一起
function SendToSceneInRange(sysarg, sceneId, range)
	local x1 = range[1]
	local y1 = range[2]
	local x2 = range[3]
	local y2 = range[4]
	x  = math.random(x1,x2)
	y  = math.random(y1,y2)
	return Actor.enterScene(sysarg, sceneId, x, y)
end

--在一个范围之内，随机一个pos
function RandPosInRange(range)
	local x1 = range[1]
	local y1 = range[2]
	local x2 = range[3]
	local y2 = range[4]
	x  = math.random(x1,x2)
	y  = math.random(y1,y2)
	return x, y
end


--[[
角色回城
Actor.returnCity(sysarg)
void CActor::ReturnCity()
触发
]]
function OnActorReturnCity( sysarg )
	--print("OnActorReturnCity...")
    CloseActivityRightPanel( sysarg )               --关闭右侧面板 
	CloseBoardPanel( sysarg )						--关闭公告牌面板
	CloseCountDownPanel( sysarg )					--关闭倒计时面板

    reEnterGuildContendScene(0, sysarg)             --行会争夺
end

--[[
角色回城
void CActor::ReturnToStaticScene()触发
]]
function OnActorReturnStaticScene( sysarg )
	--print("OnActorReturnStaticScene...")
	CloseActivityRightPanel( sysarg )				--关闭右侧面板
	CloseBoardPanel( sysarg )						--关闭公告牌面板
	CloseCountDownPanel( sysarg )					--关闭倒计时面板
end

--踢出副本内玩家
function CommonTickPlayerOutFuben( fubenPtr )
	local playerList = LuaHelp.getFbActorList(fubenPtr) or {}
	for i, player in ipairs( playerList or {} ) do
		Actor.exitFuben( player )
	end
end

--踢出场景内玩家
function CommonTickPlayerOutScene( sceneId )
	local playerList = LuaHelp.getSceneActorListById( sceneId ) or {}
	for i, player in ipairs( playerList or {} ) do
		Actor.returnCity( player )
	end
end

--[[
已经退出场景
注意：手工退出、下线、被T出，GM指令Move出都会触发
]]
function OnCommonSceneExit( sysarg, sceneId, fubenId )
	--print("OnCommonSceneExit, sceneId="..sceneId..", fubenId="..fubenId)
	CloseActivityRightPanel(sysarg)
	CloseCountDownPanel(sysarg)
	CloseBoardPanel( sysarg )
	CloseCountDownPanel( sysarg )					--关闭倒计时面板
end


--[[
已经退出副本
注意：手工退出、下线、被T出，GM指令Move出都会触发
]]
function OnCommonFubenExit( sysarg, fubenId, sceneId )
	--print("OnCommonFubenExit, fubenId="..fubenId..", sceneId="..sceneId)
	CloseActivityRightPanel(sysarg)
	CloseBoardPanel( sysarg )
	CloseCountDownPanel( sysarg )					--关闭倒计时面板

	--Actor.postEntityScriptDelayMsg(Killer, FuBen[fubenId].quitCountDownTime*1000, 0, 16,0,0,0,0,false)
	Actor.removeEntityScriptDelayMsg( sysarg, 16 ) 		--已经离开副本，清除离开当前副本的延迟处理
end


--[[
手工离开场景
1、关闭副本
]]
function OnCommonSceneHandExit( sysarg )
	--print("OnCommonSceneHandExit...")
	local fubenId = Actor.getFubenId( sysarg )
	if fubenId > 0 then
		local fubenHandle = Actor.getFubenHandle( sysarg )
		if fubenHandle then
			Fuben.setFubenTime( fubenHandle, 1 )	--手工离开，关闭副本,然后触发 OnSingleCommonFubenTimeout()
		end
	end
end

--[[
离开个人场景、副本
离开多人场景不要调用此方法
]]
function OnCommonPersonSceneExit( sysarg )
	--print("OnCommonPersonSceneExit...")
	local logoutFlag = Actor.getLogoutFlag( sysarg )			--是否是下线
	--[[
	if logoutFlag then
		print("OnCommonPersonSceneExit, logoutFlag = true")
	else
		print("OnCommonPersonSceneExit, logoutFlag = false")
	end
	]]

	CloseActivityRightPanel( sysarg )				--关闭右侧面板
	CloseBoardPanel( sysarg )						--关闭公告牌面板
	CloseCountDownPanel( sysarg )					--关闭倒计时面板

	local fubenId = Actor.getFubenId( sysarg )
	if not logoutFlag and fubenId > 0 then						--离开副本（非下线）才关闭副本
		local fubenHandle = Actor.getFubenHandle( sysarg )
		if fubenHandle then
			Fuben.setFubenTime( fubenHandle, 1 )	--手工离开，关闭副本,然后触发 OnSingleCommonFubenTimeout()
		end
	end
end

--[[
通用副本下线处理
1、掉线保护
]]
function OnCommonFubenLogout( sysarg )
	DroplineSaveFubenHandler( sysarg )			--副本内下线，要支持掉线保护

	local sceneId 	= Actor.getSceneId( sysarg )
	local fubenPtr 	= Actor.getFubenPrt(sysarg)
	local fubenId 	= Fuben.getFuBenId(fubenPtr)
	--print("OnLogoutGuildAdventure, sceneId="..sceneId..", fubenId="..fubenId)
	local actorId 	= Actor.getActorId( sysarg )
	local actorName	= Actor.getName( sysarg )
	local sceneId 	= Actor.getSceneId( sysarg )
	local fubenId 	= Actor.getFubenId( sysarg )
	System.sendCommonLog( GameLog.clFubenDropReset_Logout, actorId, actorName , 0, sceneId, fubenId,'','',"fuben logout")
end

--[[
单人副本时间到
进入副本时，要设置副本的ownerId，Fuben.setOwnerId( fubenPtr, actorId )
这里，玩家可能已经离开了副本
]]
function OnSingleCommonFubenTimeout( fubenPtr )
	local fubenId = Fuben.getFuBenId(fubenPtr)
	if fubenId <= 0 then
		return
	end

	local ownerId  = Fuben.getOwnerId( fubenPtr )			--副本Owner
	if ownerId <= 0 then
		return
	end
	--print("OnSingleCommonFubenTimeout, ownerId="..ownerId)
	local actorPtr = System.getEntityPtrByActorID(ownerId)
	if not actorPtr then
		return
	end

	--[[一些特殊处理
	actorPtr:此时玩家可能在副本中，也可能在副本外，取副本数据要使用fubenPtr
	]]
	if IsInGuildAdventure( fubenId ) then 				    --行会宝藏探险
		local advCfg = GetGuildAdventureCfg( fubenId )
		OnGuildAdventureOver( actorPtr, advCfg, 0 )			--失败了
	elseif IsInBoodFightFuben( fubenId ) then				--血战到底
		OnBloodFightOver( fubenPtr )
	elseif IsInKongFuMasterFuben( fubenId ) then			--练功师
		OnKongFuMasterOver( actorPtr, fubenPtr, 0 )
	elseif IsInSkyTowerFubenById( fubenId ) then			--通天塔
		OnSkyTowerOver( actorPtr, fubenPtr, 0, nil )
	end
end


--[[
副本中恢复上线
需要掉线恢复的单人副本，其配置要配置 reloginType = 1，
从外部进入副本时， CommonEnterScence()调用Fuben.setOwnerId()，设置副本的ownerId
checkOwner：核对 actorId 必须与 ownerId相同，以防误进入
checkGuild: 多人副本，检查角色是否这个行会的
]]
function ProcLoginCommonFuben( sysarg, fubenPtr, reloginIdx )
	--print("ProcLoginCommonFuben, reloginIdx="..reloginIdx)
	if not fubenPtr then
		return
	end

	local fubenId  = Fuben.getFuBenId( fubenPtr )
	if fubenId <= 0 then
		return
	end

	local fubenHandle = Fuben.getFubenHandle( fubenPtr )
	--print("ProcLoginCommonFuben, fubenHandle="..fubenHandle)
	if fubenHandle <= 0 then
		return
	end

	if not Fuben.isFubenExist( fubenHandle ) then			--副本已经不存在（被撤销）了
		return
	end

	local checkOwner 	= GlobalLuaConfig.reloginFuben.reloginProc[reloginIdx].checkOwner
	local checkGuild 	= GlobalLuaConfig.reloginFuben.reloginProc[reloginIdx].checkGuild
	local getFubenFunc 	= GlobalLuaConfig.reloginFuben.reloginProc[reloginIdx].getFubenFunc

	if not getFubenFunc then
		print("ProcLoginCommonFuben, no getFubenFunc ")
		return
	end

	local fubenCfg  	= nil
	local FuncAfterEnter= nil		--进入副本后，需要执行的方法
	local loginLog  	= ""
	local loginLogOk 	= ""
	--[[
	if IsMaterialFuben( fubenId ) then
		fubenCfg, FuncAfterEnter, loginLog, loginLogOk = GetElemsForReLoginMaterialFuben( fubenId )
	elseif IsInGuildAdventure( fubenId )  then			--登陆行会宝藏探险副本
		fubenCfg, FuncAfterEnter, loginLog, loginLogOk = GetElemsForReLoginGuildAdventure( fubenId )
	elseif IsInArenaBossFuben( fubenId )  then		    --登陆擂台BOSS副本
		fubenCfg, FuncAfterEnter, loginLog, loginLogOk = GetElemsForReLoginArenaBoss( fubenId )
	elseif IsInGuildBossFuben( fubenId )  then		    --登陆行会BOSS副本
		fubenCfg, FuncAfterEnter, loginLog, loginLogOk = GetElemsForReLoginGuildBoss( fubenPtr )
	elseif IsInPersonBossFuben( fubenId ) then 		    --登陆个人BOSS副本
		fubenCfg, FuncAfterEnter, loginLog, loginLogOk = GetElemsForReLoginPersonBoss( fubenId )
	elseif IsInTeamFuben( fubenId ) then			    --登陆团队副本
		fubenCfg, FuncAfterEnter, loginLog, loginLogOk = GetElemsForReLoginTeamFuben( fubenId )
		local teamId  = Fuben.getFbValue( fubenPtr, TEAMFUBEN_TEAM_ID )
		if teamId <= 0 then		--副本已经没有团队了
			return
		end
	end
	]]

	fubenCfg, FuncAfterEnter, loginLog, loginLogOk = getFubenFunc( fubenPtr )
	if reloginIdx == GlobalLuaConfig.reloginFuben.teamFuben then		--登陆团队副本
		local teamId  = Fuben.getFbValue( fubenPtr, TEAMFUBEN_TEAM_ID )
		if teamId <= 0 then		--副本已经没有团队了
			return
		end

		--在判断玩家是否属于这个团队(角色在团队副本中下线，不会离开团队)
		if not Fuben.isInFubenTeam( sysarg, teamId ) then
			return
		end
	end	

	if not fubenCfg then
		return
	end

	if fubenId ~= fubenCfg.fubenId then 			--以正式副本为准
		return
	end

	--这里预防曾经有某玩家保存的副本handle正好与此副本相同的情况
	local actorId 	= Actor.getActorId( sysarg )
	local actorName	= Actor.getName( sysarg )
	System.sendCommonLog( GameLog.clFubenDropReset_LoginTry, actorId, actorName , 0, 0, fubenId,'','', loginLog )

	if checkOwner then 		--需要检查ownerId，一般用于单人副本
		local ownerId = Fuben.getOwnerId( fubenPtr )			--副本Owner
	    --print("ProcLoginCommonFuben, actorId="..actorId..", ownerId="..ownerId)
		if ownerId <= 0 or actorId ~= ownerId then
			return
		end
	end

	if checkGuild then
		local actorGuildId = Actor.getGuildId(sysarg)
		local fubenGuildId = Fuben.getGuildId( fubenPtr )
		--print("ProcLoginCommonFuben, actorGuildId="..actorGuildId..", fubenGuildId="..fubenGuildId)
		if actorGuildId ~= fubenGuildId then
			return
		end
	end
	
	local enterPos = fubenCfg.enterPos
	if not enterPos then
		return
	end
	
	if Actor.enterFuBen(sysarg, fubenHandle, fubenCfg.sceneId, enterPos[1], enterPos[2]) then
		if FuncAfterEnter then				       --有些副本可能没有左侧面板
			FuncAfterEnter( sysarg, fubenCfg )	   --玩家已经进入副本
		end
		System.sendCommonLog( GameLog.clFubenDropReset_LoginOk, actorId, actorName , 0, fubenCfg.sceneId, fubenId, '', '', loginLogOk )
	end
end

--[[
玩家进入场景
主要处理CommonSceneConfig配置
]]
function OnActorEnterCommonScene( sysarg, sceneId )
	local sceneCfg = CommonSceneConfig[sceneId]
	if sceneCfg then
		if sceneCfg.enterBuff then								          --进入场景加的buff
			local buffs = sceneCfg.enterBuff or {}
			for i, buffId in ipairs( buffs or {} ) do
				if not Actor.hasBuffById( sysarg, buffId ) then
					Actor.addBuffById( sysarg, buffId )
				end
			end
		end

		if sceneCfg.enterBuffBySex then									  --进入场景加的buff（按性别）
			local sex = Actor.getIntProperty( sysarg, PROP_ACTOR_SEX )    --0-男，1-女
			local buffs = sceneCfg.enterBuffBySex[sex+1] or {}
			for i, buffId in ipairs( buffs or {} ) do
				if not Actor.hasBuffById( sysarg, buffId ) then
					Actor.addBuffById( sysarg, buffId )
				end
			end
		end

		if sceneCfg.enterBuffByJob then										--进入场景加的buff（按职业）
			local job = Actor.getIntProperty( sysarg,PROP_ACTOR_VOCATION ) 	--1-战、2-法、3-道
			local buffs = sceneCfg.enterBuffByJob[job] or {}
			for i, buffId in ipairs( buffs or {} ) do
				if not Actor.hasBuffById( sysarg, buffId ) then
					Actor.addBuffById( sysarg, buffId )
				end
			end
		end
	end
end

--[[
玩家离开场景
主要处理CommonSceneConfig配置
]]
function OnActorExitCommonScene( sysarg, sceneId )
	local sceneCfg = CommonSceneConfig[sceneId]
	if sceneCfg then
		if sceneCfg.enterBuff then
			local buffs = sceneCfg.enterBuff or {}
			for i, buffId in ipairs( buffs or {} ) do
				if Actor.hasBuffById( sysarg, buffId ) then
					Actor.delBuffById( sysarg, buffId )
				end
			end
		end

		if sceneCfg.enterBuffBySex then
			local sex = Actor.getIntProperty( sysarg, PROP_ACTOR_SEX )    --0-男，1-女
			local buffs = sceneCfg.enterBuffBySex[sex+1] or {}
			for i, buffId in ipairs( buffs or {} ) do
				if Actor.hasBuffById( sysarg, buffId ) then
					Actor.delBuffById( sysarg, buffId )
				end
			end
		end

		if sceneCfg.enterBuffBySex then 			--这些buff都要删除
			local maleBuffs = sceneCfg.enterBuffBySex[1] or {}
			for i, buffId in ipairs( maleBuffs or {} ) do
				if Actor.hasBuffById( sysarg, buffId ) then
					Actor.delBuffById( sysarg, buffId )
				end
			end

			local femaleBuffs = sceneCfg.enterBuffBySex[2] or {}
			for i, buffId in ipairs( femaleBuffs or {} ) do
				if Actor.hasBuffById( sysarg, buffId ) then
					Actor.delBuffById( sysarg, buffId )
				end
			end
		end
	end
end

